import { copyToText } from '@utils/copyToClipboard';
import { createButton } from '@utils/createButton';
import { createDialog } from '@utils/createDialog';
import { createLoading } from '@utils/createLoading';
import { downloadResource } from '@utils/downloadResource';
import { getPersonEmail } from '@utils/getPersonEmail';
import { showMessage } from '@utils/showMessage';
import { onFormSubmit } from '@utils/onFormSubmit';
import { showHideFormItemsByData } from '@utils/showHideFormItemsByData';
import { persons as personData } from '@const';
import { MessageTypeEnum } from '@enum/message-type.enum';
import { assignToList } from '@components/assignToList.vue';
import { iframeCallback } from '@utils/iframeCallback';
import { CollectedBug, getCollectInfo, setCollectionIcon } from '@utils/bugCollection';
import { addBugWithRepeatCheck, isBugInReport, removeBugFromReport } from '@utils/getReportBugs';

export default () => {
  if (!localStorage.getItem('personsMap')) {
    localStorage.setItem('personsMap', JSON.stringify(personData));
  }

  const persons = JSON.parse(localStorage.getItem('personsMap') ?? '{}');
  const table1 = document.querySelector('#bz_show_bug_column_1') as HTMLLinkElement;
  const table2 = document.querySelector('#bz_show_bug_column_2') as HTMLLinkElement;
  const reporterNode = document.querySelector('#bz_show_bug_column_2 .vcard .email') as HTMLLinkElement;
  const table2AllRows = Array.from(document.querySelectorAll('#bz_show_bug_column_2 tr')) as HTMLElement[];
  const reporterEmail = getPersonEmail(reporterNode?.href ?? '') as string;
  const reportNodes = Array.from(document.querySelectorAll('.vcard .email .fn')) as HTMLSpanElement[];
  const historyBtn = document.querySelector('#bz_show_bug_column_2 tr:nth-child(2) a') as HTMLLinkElement;;

  const editTitleBtn = document.querySelector('#editme_action') as HTMLLinkElement;
  const assigneeEditBtn = document.querySelector('#bz_assignee_edit_action') as HTMLLinkElement;
  const assigneeTakeBtn = document.querySelector('#bz_assignee_take_action') as HTMLLinkElement;
  const markDuplicateBtn = document.querySelector('#dup_id_discoverable_action') as HTMLDivElement;
  const markDuplicateBox = document.querySelector('#dup_id_discoverable') as HTMLDivElement;
  const duplicateSettings = document.querySelector('#duplicate_settings') as HTMLSpanElement;
  const replaceTitleInput = document.querySelector('#summary_alias_input') as HTMLInputElement;
  const commentTextArea = document.querySelector('#comment') as HTMLTextAreaElement;
  const attachmentDetails = Array.from(document.querySelectorAll('#attachment_table td[valign="top"]:nth-child(2) a')) as HTMLLinkElement[];

  const saveFormBtns = Array.from(document.querySelectorAll('.knob-buttons input')) as HTMLInputElement[];
  const bugStatus = document.querySelector('#bug_status') as HTMLSelectElement;
  const resolution = document.querySelector('#resolution') as HTMLSelectElement;
  const resolutionSettings = document.querySelector('#resolution_settings') as HTMLSpanElement;

  const assigneeInputNode = document.querySelector('#bz_assignee_input');
  const assigneeEditNode = document.querySelector('#bz_assignee_edit_container') as HTMLDivElement;
  const assignToSelect = document.querySelector('#assigned_to') as HTMLInputElement;
  
  const bugTitleBox = document.querySelector('#summary_alias_container') as HTMLDivElement;
  const bugTitleNode = document.querySelector('#short_desc_nonedit_display') as HTMLSpanElement;
  const bugIDNode = document.querySelector('.bz_alias_short_desc_container a b') as HTMLElement;
  const bugId = (bugIDNode.innerText as string).match(/(\d+)$/)?.[1] as string;

  const effectNode = document.querySelector('#cf_effect') as HTMLSelectElement;
  const bugComments0 = document.querySelector("#comment_text_0") as HTMLPreElement;
  const bzSpacerNodes = Array.from(document.querySelectorAll('#bz_show_bug_column_1 tr:has(td[class="bz_section_spacer"])')) as HTMLSpanElement[];
  const navigationNode = document.querySelector('.navigation');
  const attachmentNode = document.querySelector('#attachment_table .bz_attach_footer a:not(a[id="view_all"])') as HTMLLinkElement;
  const attachmentViewAll = document.querySelector('#attachment_table .bz_attach_footer a[id="view_all"]') as HTMLLinkElement;

  if (table1 && table2) {
    const table1Width = table1.clientWidth;
    table2.style.setProperty("width", Math.round(document.body.clientWidth - table1Width) + "px");
  }

  if (historyBtn) {
    historyBtn.innerText = '历史记录';
    historyBtn.classList.add('custom-button');
    historyBtn.classList.add('plain-button');
    historyBtn.style.margin = '0 6px';

    historyBtn.addEventListener('click', (e) => {
      e.preventDefault();

      createDialog({
        title: '历史记录',
        hideOk: true,
        cancelText: '关闭',
        bodyStyle: 'width: 60vw; height: 60vh;',
        body: `
          <iframe id='history-iframe' src='${historyBtn.href}' style='width: 100%; height: 100%; border: none;'></iframe>
        `,
        onMount: () => {
          iframeCallback('history-iframe', (contentDocument) => {
            const header = contentDocument.querySelector("#header") as HTMLDivElement;
            const footer = contentDocument.querySelector("#footer") as HTMLDivElement;

            if (header) {
              header.remove();
            }

            if (footer) {
              footer.remove()
            }
          })
        }
      })
    })
  }

  reportNodes.forEach((node: HTMLSpanElement) => {
    if (Object.keys(persons).includes(node.innerText)) {
      // @ts-ignore
      node.innerText = persons[node.innerText];
    } else if(node.innerText.includes("-")) {
      const splits = node.innerText.split("-");
      const left = splits[0];
      const right = splits[1];

      if(/^[a-zA-Z0-9]+$/.test(left)) {
        node.innerText = persons[left];
      }

      if(/^[a-zA-Z0-9]+$/.test(right)) {
        node.innerText = persons[right];
      }
    }
  })

  createButton(
    '复制报告人姓名',
    (button) => {
      button.classList.add('plain-button');
      (reporterNode?.parentNode as HTMLElement)?.insertBefore(button, reporterNode.nextSibling);
    },
    () => {
      copyToText(reporterNode.innerText);
    }
  )

  if (bzSpacerNodes.length) {
    bzSpacerNodes.forEach((node) => {
      node.style.display = 'none';
    })
  }

  if (effectNode && !effectNode.value) {
    effectNode.value = '无';
  }

  if (bugTitleBox && bugTitleNode && bugIDNode) {
    const reportBtn = createButton(
      '日报/移除',
      (button) => {
        button.classList.add('custom-button');

        if(!isBugInReport(bugId)) {
          button.innerText = '添加日报';
        }
        else {
          button.classList.add('plain-button');
          button.innerText = '移除日报';
        }
    
        (bugTitleBox.parentNode as HTMLElement).insertBefore(button, bugTitleBox.nextSibling);
      },
      () => {
        if(!isBugInReport(bugId)) {
          addBugWithRepeatCheck({
            id: bugId,
            name: bugTitleNode.innerText,
            url: window.location.href,
          })
          reportBtn.classList.add('plain-button');
          reportBtn.innerText = '移除日报';
        }
        else {
          removeBugFromReport(bugId);
          reportBtn.classList.remove('plain-button');
          reportBtn.innerText = '添加日报';
        }
      }
    );
    createButton(
      '复制 Commit',
      (button) => {
        button.classList.add('plain-button');
        (bugTitleBox.parentNode as HTMLElement).insertBefore(button, bugTitleBox.nextSibling);
      },
      () => {
        copyToText(`git commit -m 'bug: ${bugId} 修复：${bugTitleNode.innerText}'`);
      }
    );
    createButton(
      '复制 URL',
      (button) => {
        button.classList.add('plain-button');
        (bugTitleBox.parentNode as HTMLElement).insertBefore(button, bugTitleBox.nextSibling);
      },
      () => {
        copyToText(window.location.href);
      }
    );
    createButton(
      '复制 ID & 标题',
      (button) => {
        button.classList.add('plain-button');
        (bugTitleBox.parentNode as HTMLElement).insertBefore(button, bugTitleBox.nextSibling);
      },
      () => {
        copyToText("Bug " + bugId + " " + bugTitleNode.innerText);
      }
    );
    createButton(
      '复制 ID',
      (button) => {
        button.classList.add('plain-button');
        (bugTitleBox.parentNode as HTMLElement).insertBefore(button, bugTitleBox.nextSibling);
      },
      () => {
        copyToText(bugId);
      }
    );
  }

  if (assigneeInputNode) {
    (assigneeInputNode.parentNode as HTMLElement).classList.add('bz_assignee_td');

    const backButton = createButton(
      '取消',
      (button) => {
        button.classList.add('plain-button');
        button.style.display = 'none';
        button.style.marginRight = '0';
        (assigneeInputNode.parentNode as HTMLElement).appendChild(button);
      },
      (_, button) => {
        assigneeInputNode.classList.add('bz_default_hidden');
        assigneeEditNode.classList.remove('bz_default_hidden');
        if (button.style.display = 'block') {
          button.style.display = 'none';

          const aLink = document.querySelector('#bz_assignee_edit_container .email') as HTMLLinkElement;
          
          if (aLink) {
            const email = getPersonEmail(aLink.href);

            if (email) {
              assignToSelect.value = email;

              const assignToAppNode = document.querySelector('#assigned_to_list_vue_app') as HTMLDivElement;

              if (assignToAppNode) {
                assignToAppNode.remove();
                assignToList();
              }
            }
          }
        }
      }
    );

    if (editTitleBtn) {
      editTitleBtn.innerText = '编辑标题';
      editTitleBtn.classList.add('custom-button');
      editTitleBtn.classList.add('plain-button');

      editTitleBtn.addEventListener('click', (e) => {
        e.preventDefault();
        replaceTitleInput.classList.remove('bz_default_hidden');
        bugTitleBox.classList.remove('bz_default_hidden');
        createDialog({
          title: '更改标题',
          body: replaceTitleInput,
          okText: '保存',
          onOk: () => {
            createDialog({
              title: '请确认',
              body: '确定更改标题?',
              bodyStyle: 'width: 300px;',
              okText: '确定',
              onOk: () => {
                onFormSubmit(saveFormBtns[0].form as HTMLFormElement, false);
              }
            })
          },
        });
      })
    }

    if (assigneeEditBtn) {
      assigneeEditBtn.innerText = '加载资源中...';
      assigneeEditBtn.classList.add('custom-button');
      assigneeEditBtn.classList.add('plain-button');
      assigneeEditBtn.classList.add('disabled-button');

      assigneeEditBtn.addEventListener('click', () => {
        assigneeInputNode.classList.remove('bz_default_hidden');
        assigneeEditNode.classList.add('bz_default_hidden');

        if((assignToSelect.nextElementSibling as HTMLSelectElement).tagName === 'BR') {
          assignToSelect.nextElementSibling?.remove();
        }

        if (backButton.style.display = 'none') {
          backButton.style.display = 'block';
        }
      })
    }

    if (assigneeTakeBtn) {
      assigneeTakeBtn.classList.add('bz_default_hidden');

      const takeNode = document.createElement("span");
      takeNode.innerText = '转给自己';
      takeNode.classList.add('custom-button');
      takeNode.classList.add('plain-button');
      const assignToPerson = assignToSelect.value;

      assigneeTakeBtn.parentNode?.insertBefore(takeNode, assigneeTakeBtn.nextSibling);

      takeNode.addEventListener('click', () => {
        createDialog({
          body: '确定将此任务转给自己?',
          bodyStyle: 'width: 400px; height: 50px;',
          okText: '确定',
          onOk: (closeDialog) => {
            assigneeTakeBtn.click();
            closeDialog();
            assigneeInputNode.querySelector('br')?.remove();
            onFormSubmit(saveFormBtns[0].form as HTMLFormElement, false);
          },
          onDestroy: () => {
            assigneeInputNode.classList.add('bz_default_hidden');
            assigneeEditNode.classList.remove('bz_default_hidden');
            assignToSelect.value = assignToPerson;
          }
        })
      })
    }
  }

  if (markDuplicateBtn) {
    markDuplicateBtn.classList.add('custom-button');
    markDuplicateBtn.classList.add('plain-button');
    markDuplicateBtn.innerText = '标记bug重复';
    const status1 = bugStatus.value;
    const status2 = resolution.value;

    const cancelBtn = createButton(
      '取消',
      (btn) => {
        btn.classList.add('plain-button');
        btn.classList.add('hide');
        duplicateSettings.parentNode?.appendChild(btn);
      },
      () => {
        duplicateSettings.classList.add('bz_default_hidden');
        markDuplicateBox.classList.remove('bz_default_hidden');
        cancelBtn.classList.add('hide');

        bugStatus.value = status1;

        if (status2) {
          resolution.value = status2;
        } else {
          resolutionSettings.classList.add('bz_default_hidden');
        }
      }
    )

    markDuplicateBtn.addEventListener('click', (e) => {
      e.preventDefault();
  
      duplicateSettings.classList.remove('bz_default_hidden');
      markDuplicateBox.classList.add('bz_default_hidden');
      cancelBtn.classList.remove('hide');
    })
  }

  if (commentTextArea) {
    commentTextArea.addEventListener('focus', () => {
      commentTextArea.rows = 10;
    })
  }

  if (attachmentDetails.length) {
    const fileNames = Array.from(document.querySelectorAll('#attachment_table td[valign="top"]:nth-child(0) b')) as HTMLElement[];
    const fileTypeNodes = Array.from(document.querySelectorAll('#attachment_table td[valign="top"]:nth-child(1) .bz_attach_extra_info')) as HTMLSpanElement[];

    attachmentDetails.forEach((attachment, index) => {
      attachment.classList.add('custom-button');
      attachment.classList.add('plain-button');

      attachment.style.margin = '6px 16px';

      const url = attachment.href.split('&')?.[0];
      const fileType = fileTypeNodes[index]?.innerText?.trim().match(/\(([^)]+)\)/)?.[1].split(', ')?.[1] ?? '';

      if (fileType.includes('zip')) {
        attachment.innerText = '下载';
      } else {
        attachment.innerText = '查看';
      }

      attachment.addEventListener('click', (e) => {
        e.preventDefault();

        if (fileType.includes('image')) {
          const loadingNode = createLoading();

          // image
          const imageBodyNode = document.createElement('div');
          imageBodyNode.classList.add('attachment-container');
          imageBodyNode.classList.add('hide');
          const imageNode = document.createElement('img');
          imageNode.src = url;
          // @ts-ignore
          imageNode.style = 'width: 100%; height: auto;';
          imageNode.addEventListener('load', () => {
            imageBodyNode.classList.remove('hide');
            imageBodyNode.classList.add('show');
            loadingNode.classList.add('hide');
          })
          imageBodyNode.appendChild(imageNode);

          const bodyNode = document.createElement('div');
          bodyNode.appendChild(loadingNode);
          bodyNode.appendChild(imageBodyNode);

          createDialog({
            title: '图片详情',
            hideOk: true,
            cancelText: '关闭',
            body: bodyNode,
          })
        } else if (fileType.includes('video')) {
          const loadingNode = createLoading();

          // image
          const videoBodyNode = document.createElement('div');
          videoBodyNode.classList.add('attachment-container');
          videoBodyNode.classList.add('hide');
          const videoNode = document.createElement('video');
          videoNode.controls = true;
          videoNode.autoplay = true;
          videoNode.loop = true;
          // @ts-ignore
          videoNode.style = 'width: 100%; height: auto;';
          const sourceNode = document.createElement('source');
          sourceNode.src = url;
          sourceNode.type = fileType;
          // @ts-ignore
          sourceNode.style = 'width: 100%; height: auto;';
          videoNode.addEventListener('canplaythrough', () => {
            videoBodyNode.classList.remove('hide');
            videoBodyNode.classList.add('show');
            loadingNode.classList.add('hide');
          })
          videoNode.appendChild(sourceNode);
          videoBodyNode.appendChild(videoNode);

          const bodyNode = document.createElement('div');
          bodyNode.appendChild(loadingNode);
          bodyNode.appendChild(videoBodyNode);

          createDialog({
            title: '视频详情',
            hideOk: true,
            cancelText: '关闭',
            body: bodyNode,
          })
        } else if (fileType.includes('zip')) {
          downloadResource(url, fileNames[index]?.innerText as string);
        } else {
          showMessage(MessageTypeEnum.ERROR, '文件不存在或者不支持查看')
        }
      })
    })
  }

  if (saveFormBtns.length) {
    saveFormBtns.forEach((saveBtn: HTMLInputElement) => {
      saveBtn.classList.add("custom-button");
      saveBtn.value = '保存表单';

      saveBtn.addEventListener('click', (e) => {
        e.preventDefault();

        const tips = [];

        if (assignToSelect.value !== reporterEmail) {
          tips.push('bug 没有指给报告人');
        }
        if (!commentTextArea.value) {
          tips.push('bug 没有填写备注');
        }
        if (!['RESOLVED', 'VERIFIED', 'CLOSED'].includes(bugStatus.value)) {
          tips.push('bug 状态不是 RESOLVED, VERIFIED, CLOSED 其中一个');
        }

        if (tips.length) {
          createDialog({
            title: '请确认',
            body: `
              <div>
                <div style='margin-bottom: 10px; font-weight: bold; font-size: 16px; opacity: 0.6;'>确定提交表单?</div>
                ${tips.map((tip, index) => `<div style='color: #757575; line-height: 20px'>${index + 1}. ${tip}</div>`).join('')}
              </div>
            `,
            style: 'transform: translate(-50%, -70%)',
            bodyStyle: 'width: 500px;',
            okText: '确定提交',
            onOk: () => {
              onFormSubmit(saveBtn.form as HTMLFormElement, true, bugId, bugTitleNode.innerText);
            }
          })
        } else {
          onFormSubmit(saveBtn.form as HTMLFormElement, true, bugId, bugTitleNode.innerText);
        }
      })
    })
  }

  if (bugComments0) {
    let text = bugComments0.innerText;
    text = text.replace("Precondition", "复现条件");
    text = text.replace("Action", "复现步骤");
    text = text.replace("Expected Result", "预期结果");
    text = text.replace("Actual Result", "实际结果");
    text = text.replace("Comment", "备注");
    bugComments0.innerText = text;
  }

  if (navigationNode) {
    const div = document.createElement('div');
    div.classList.add('flex-justify-space-between');
    const parentNode = navigationNode.parentNode as HTMLDivElement;
    parentNode.insertBefore(div, navigationNode.nextSibling);
    div.appendChild(navigationNode);

    const collectionNode = document.createElement('div');
    collectionNode.classList.add('flex-center');
    setCollectionIcon(collectionNode, bugIDNode.innerText);
    div.appendChild(collectionNode);

    const collectBugNode1 = document.getElementById('collect-bug') as HTMLSpanElement;

    if (collectBugNode1) {
      const callback = (_: Event, collectBugNode: HTMLSpanElement) => {
        const {collectedBugs, hasCollected} = getCollectInfo(bugIDNode.innerText);

        let newBugs = {
          list: collectedBugs,
        }

        if (!hasCollected) {
          newBugs = {
            list: [...collectedBugs, { id: bugIDNode.innerText, title: bugTitleNode.innerText, url: window.location.href }],
          }

          if (collectBugNode.dataset.type !== 'no-collected') {
            showMessage(MessageTypeEnum.ERROR, '数据与页面状态不一致，页面刷新后重试');

            setTimeout(() => {
              window.location.reload();
            }, 1000);

            return;
          }
          showMessage(MessageTypeEnum.SUCCESS, '收藏成功');
        } else {
          newBugs = {
            list: collectedBugs.length > 0 && collectedBugs.filter((bug: CollectedBug) => bug.id !== bugIDNode.innerText),
          }

          if (collectBugNode.dataset.type !== 'collected') {
            showMessage(MessageTypeEnum.ERROR, '数据与页面状态不一致，页面刷新后重试');

            setTimeout(() => {
              window.location.reload();
            }, 1000);

            return;
          }

          showMessage(MessageTypeEnum.SUCCESS, '已取消收藏');
        }
        localStorage.setItem('collected-bugs', JSON.stringify(newBugs));
        setCollectionIcon(collectionNode, bugIDNode.innerText);

        const collectBugNode2 = document.getElementById('collect-bug') as HTMLSpanElement;

        if (collectBugNode2) {
          collectBugNode2.addEventListener('click', (e) => callback(e, collectBugNode2));
        }
      };

      collectBugNode1.addEventListener('click', (e) => callback(e, collectBugNode1));
    }
  }

  if (attachmentNode) {
    attachmentNode.classList.add("custom-button");
    attachmentNode.innerText = "添加附件";
    attachmentNode.addEventListener('click', (e) => {
      e.preventDefault();

      createDialog({
        title: '上传附件',
        okText: '关闭弹窗 & 刷新页面',
        cancelText: '关闭',
        bodyStyle: 'width: 60vw; height: 70vh;',
        body: `
          <iframe id='attachment-iframe' src='${attachmentNode.href}' style='width: 100%; height: 100%; border: none;'></iframe>
          <div style='margin-top: 10px; color: grey; position: fixed; bottom: 10px;'>
            备注：点击 Submit 按钮上传，上传后点击右下角关闭并刷新按钮刷新整个页面，查看上传结果
          </div>
        `,
        onMount: () => {
          iframeCallback('attachment-iframe', (contentDocument) => {
            const header = contentDocument.querySelector("#header") as HTMLDivElement;
            const footer = contentDocument.querySelector("#footer") as HTMLDivElement;

            if (header) {
              header.remove();
            }

            if (footer) {
              footer.remove()
            }
          })
        },
        onOk: () => {
          window.location.reload();
        },
      })
    })
  }

  if (attachmentViewAll) {
    attachmentViewAll.remove();
  }

  if (table2AllRows?.length) {
    table2AllRows.forEach((row) => {
      if (row.firstElementChild && (row.firstElementChild as HTMLElement).classList.contains("bz_hidden_field")) {
        (row.firstElementChild as HTMLElement).classList.remove("bz_hidden_field");
      }
      if (row.firstElementChild?.nextElementSibling && (row.firstElementChild.nextElementSibling as HTMLElement).classList.contains("bz_hidden_field")) {
        (row.firstElementChild.nextElementSibling as HTMLElement).classList.remove("bz_hidden_field");
      }
    })
  }

  showHideFormItemsByData();
}
